package net.oov.identify;

import java.util.Map;
import java.util.Map.Entry;

import net.oov.identify.StatusTree.TreeNode;
import net.oov.identify.model.FreqCheck;

/**
 * Buck in ice age 3
 * having infinite brave
 * to help us discern words
 * from strings
 * 
 * @author huangsui.cn
 *
 */
public class Buck implements FreqCheck{
	
	Map<Character, StatusTree> freqDic = null;
	
	public Buck(){
		
	}
	
	public Buck(Map<Character, StatusTree> freqDic){
		this.freqDic = freqDic;
	}
		
	/**
	 * find the most depth tree node for the char sequence
	 * statusTree has the same value of key as the first char of char sequence
	 * @param statusTree
	 * @param charSequence
	 * @return
	 */
	public TreeNode findTreeNode(StatusTree statusTree, CharSequence charSequence){
		
		return findTreeNode(statusTree.rootNode(), charSequence);

	}
	
	/**
	 * find the char sequence in the container
	 * @param container
	 * @param charSequence
	 * @return
	 */
	public TreeNode findTreeNode(Map<Character, StatusTree> freqDic, CharSequence charSequence){
		StatusTree statusTree = freqDic.get(charSequence.charAt(0));
		if(statusTree == null)return null;
		return findTreeNode(statusTree.rootNode(), charSequence);
	}
	
	/**
	 * find the char sequence in the container
	 * @param container
	 * @param charSequence
	 * @return
	 */
	public TreeNode findTreeNode(CharSequence charSequence){
		StatusTree statusTree = freqDic.get(charSequence.charAt(0));
		return findTreeNode(statusTree.rootNode(), charSequence);
	}
	
	/**
	 * find TreeNode with key of the offset char of charSequence in the subNodes of treeNode 
	 * @param treeNode
	 * @param charSequence
	 * @param offset
	 * @return
	 */
	private TreeNode findTreeNode(TreeNode treeNode, CharSequence charSequence){
		
		TreeNode subNode = null;
		if(treeNode.getOffset()+1==charSequence.length() ){//current node match the charSequence
			if(treeNode.isEndpoint()){// now every node is endPoint
				return treeNode;
			}else{
				return null;
			}
		}else if(treeNode.isLeaf()){
			return null;
		}else if( (subNode = treeNode.subNode(charSequence.charAt(treeNode.getOffset()+1)))==null){
			return null;
		}
		return findTreeNode(subNode, charSequence);

	}
	
	
	/**
	 * get the frequency of char sequence
	 * @param cs
	 * @return
	 */
	public Integer freq(CharSequence cs){
		if(freqDic == null)return null;
		TreeNode tn = this.findTreeNode(freqDic, cs);
		if(tn==null)return 0;
		return tn.freq();
	}
	
	/**
	 * get the tree node with the max frequency in the next level of CharSequence
	 * @param cs
	 * @return
	 */
	public TreeNode getNextNodeWithMaxFreq(CharSequence cs,Character[] saveNextCh){
		
		if(freqDic == null)return null;
		TreeNode tn = this.findTreeNode(freqDic, cs);
		if(tn==null || tn.subNodes()==null)return null;
		int freq = 0;
		TreeNode ret = null;
		for(Entry<Character, TreeNode>en:tn.subNodes().entrySet()){
			if(freq<en.getValue().freq()){
				ret = en.getValue();
				freq = ret.freq();
				saveNextCh[0] = en.getKey();
			}
		}
		return ret;
	}
	
	/**
	 * get the frequency of char sequence as a whole term
	 * @param cs
	 * @return
	 */
	public Integer freqWhole(CharSequence cs){
		if(freqDic == null)return 0;
		TreeNode tn = this.findTreeNode(freqDic, cs);
		if(tn==null)return 0;
		return tn.freqWhole();
	}
	
}
